﻿using Microsoft.OData.Client;
using System.Collections.Concurrent;

namespace EasyXaf.ObjectSpaces.OData;

public class ODataContext : DataServiceContext, IDisposable
{
    private readonly ConcurrentQueue<Uri> _entryEntityIds = new();

    public ODataContext(Uri serviceRoot, IODataObjectSpace objectSpace)
        : base(serviceRoot)
    {
        Configurations.ResponsePipeline.OnEntryEnded(args =>
        {
            _entryEntityIds.Enqueue(args.Entry.Id);
        });

        Configurations.ResponsePipeline.OnFeedEnded(args =>
        {
            while (!_entryEntityIds.IsEmpty)
            {
                if (_entryEntityIds.TryDequeue(out var entityId))
                {
                    var entityDescriptor = Entities.FirstOrDefault(e => e.Identity == entityId);
                    if (entityDescriptor != null)
                    {
                        objectSpace.AcceptObject(entityDescriptor.Entity);
                    }
                }
            }
        });
    }

    public void Dispose()
    {
        foreach (var entityDescriptor in Entities)
        {
            if (entityDescriptor.Entity is IDisposable entity)
            {
                entity.Dispose();
            }
            Detach(entityDescriptor);
        }

        foreach (var linkDescriptor in Links)
        {
            if (linkDescriptor.Target is IDisposable entity)
            {
                entity.Dispose();
            }
            DetachLink(linkDescriptor.Source, linkDescriptor.SourceProperty, linkDescriptor.Target);
        }

        GC.SuppressFinalize(this);
    }
}
